package com.talent.core.protocol.mqtt.handler;

import com.talent.core.protocol.mqtt.TlMqttSession;
import com.talent.core.protocol.mqtt.config.Constant;
import com.talent.core.protocol.mqtt.enums.TlMqttMessageType;
import com.talent.core.protocol.mqtt.model.entity.TlSubClient;
import com.talent.core.protocol.mqtt.model.entity.TlTopic;
import com.talent.core.protocol.mqtt.model.fix.TlMqttFixedHead;
import com.talent.core.protocol.mqtt.model.payload.TlMqttSubAckPayload;
import com.talent.core.protocol.mqtt.model.request.TlMqttPublishReq;
import com.talent.core.protocol.mqtt.model.request.TlMqttSubscribeReq;
import com.talent.core.protocol.mqtt.model.response.TlMqttSubAck;
import com.talent.core.protocol.mqtt.model.variable.TlMqttSubAckVariableHead;
import com.talent.core.protocol.mqtt.store.IMqttStore;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.util.AttributeKey;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;
import java.util.Set;

/**
 * @ClassName：ConnectHandler
 * @Author: hszhou
 * @Date: 2024/11/25 11:06
 * @Description: 必须描述类做什么事情, 实现什么功能
 */
@ChannelHandler.Sharable
public class TlMqttSubScribeHandler extends SimpleChannelInboundHandler<TlMqttSubscribeReq> {

    private static final  Logger logger = LoggerFactory.getLogger(TlMqttSubScribeHandler.class);

    private final IMqttStore mqttStore;


    public TlMqttSubScribeHandler(IMqttStore mqttStore){
        this.mqttStore = mqttStore;
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, TlMqttSubscribeReq msg) throws Exception {
        logger.debug("进入【SUBSCRIBE】处理器");

        List<TlTopic> topics =  msg.getPayload().getTopics();
        String clientId = ctx.channel().attr(AttributeKey.valueOf(Constant.CLIENT_ID)).get().toString();

        TlMqttSession mqttSession = mqttStore.getSessionByClientId(clientId);
        /**
         * 需要将客户端订阅的主题进行保存起来
         * 后面根据这个主题就能够立马找到对应的客户端 key就是主题的名称 最好能够获取到这个主题的订阅的qos等级,然后获取到这个客户端通道 将消息转发给他
         */
        for (TlTopic topic : topics) {
            //构建对向存储
            TlSubClient client = new TlSubClient(topic.getQos(),clientId,topic.getName(),mqttSession);
            logger.info("客户端{}订阅了主题{}",clientId,topic);
            mqttStore.putSubClient(client);
            //查询这个主题是否存在保留消息 如果有就发送
            TlMqttPublishReq retainMessage = mqttStore.getRetainMessageByTopic(topic.getName());
            if(retainMessage!=null){
                ctx.channel().writeAndFlush(retainMessage);
            }
            Set<TlTopic> subTopics = mqttSession.getTopics();
            subTopics.add(topic);
            mqttSession.setTopics(subTopics);

        }

        TlMqttSubAck res = new TlMqttSubAck();
        //消息id默认2个字节
        int length=Constant.SHORT_LENGTH;
        length+=topics.size();
        TlMqttFixedHead fixedHead = new TlMqttFixedHead();
        fixedHead.setLength(length);
        fixedHead.setMessageType(TlMqttMessageType.SUBACK.getValue());
        res.setFixedHead(fixedHead);


        TlMqttSubAckVariableHead variableHead=new TlMqttSubAckVariableHead();
        int messageId = msg.getVariableHead().getMessageId();
        variableHead.setMessageId(messageId);
        res.setVariableHead(variableHead);


        int[] codes = new int[topics.size()];
        for (int i = 0; i < topics.size(); i++) {
            codes[i]=topics.get(i).getQos();
        }
        TlMqttSubAckPayload payload = new TlMqttSubAckPayload();
        payload.setCodes(codes);
        res.setPayload(payload);
        ctx.channel().writeAndFlush(res);
        logger.debug("构建【SUBACK】消息返回");

    }
}
